package pzl.com;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;

/**
 * scrollTo移动了画板canvas，但其中任然强制绘制了，ondraw被回调了
 */
public class ChartView2 extends View {
    private static final String TAG = "ChartView2";
    private Paint mPaint;
    /**
     * 柱形图颜色
     */
    private int mHistogramColor = Color.parseColor("#4c9ff2");
    /**
     * 折线图颜色
     */
    private int mBrokenLineColor = Color.parseColor("#b696d7");
    /**
     * 坐标底线颜色
     */
    private int mCoordinateColor = Color.parseColor("#000000");
    /**
     * 坐标底线宽度
     */
    private float mCoordinateStrokeWidth = 2f;
    /**
     * 折线图宽度
     */
    private float mBrokenLineStrokeWidth = 4f;
    /**
     * 折线图折点半径
     */
    private float mBrokenLineRadius = 4f;
    /**
     * 柱形图宽度
     */
    private float mHistogramStrokeWidth = 4f;
    private int mViewHeight;
    private int mViewWidth;
    /**
     * 图表内容总宽度，segment数*xunit+一图例宽度
     */
    private float mContentWidth;
    /**
     * view padding
     */
    private int mPaddingTop, mPaddingBottom;
    /**
     * 段数
     * 一屏数据=mSegments+1
     */
    private int mSegments;
    /**
     * 一屏数据个数
     */
    private int mScreenShow;
    /**
     * Chart绘制区域
     */
    private int mLengthX, mLengthY;
    /**
     * x轴单位间隔距离
     */
    private float mUnitX;
    /**
     * y轴单位距离
     */
    private float mUnitY;
    private float mValueMax;
    private ArrayList<PointF> mData;
    /**
     * 背景色
     */
    private ColorDrawable mBgColor;
    private float mXold, mXnew;
    /**
     * 默认最小宽高
     */
    private int mDefaultMinWidth = 200;
    private int mDefaultMinHeight = 140;
    /**
     * 事件界
     */
    private RectF mRectFChartViewTouch;
    private Path mPath;
    /**
     * 0 柱形；1 折线
     */
    public static final int HISTOGRAM = 0;
    public static final int BROKENLINE = 1;
    private int mMode = HISTOGRAM;

    private int mOldFrontIndex = 0;
    /**
     * 当前屏第一个显示数据的位置
     */
    private int mFrontIndex = 0;
    /**
     * 当前屏最后一个显示数据的位置
     */
    private int mBehindIndex = 0;
    /**
     * x单位距离偏移比
     */
    private float mOffsetRate = 0f;
    /**
     * 默认chartTouch有效响应区域
     */
    private float mDefaultChartTouchArea = 20;

    private void init(Context context, AttributeSet attrs) {
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ChartView);
        mMode = ta.getInt(R.styleable.ChartView_mode, HISTOGRAM);
        mScreenShow = ta.getInt(R.styleable.ChartView_screenShow, 50);
        mSegments = mScreenShow - 1;
        ta.recycle();

        mPath = new Path();

        mPaint = new Paint();
        setLayerType(LAYER_TYPE_SOFTWARE, mPaint);//default hardware;Path too large to be rendered into a texture
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.STROKE);

        mPaddingBottom = getPaddingBottom();
        mPaddingTop = getPaddingTop();

        mBgColor = (ColorDrawable) getBackground();

        mFrontIndex = 0;
        mOldFrontIndex = 0;
        mBehindIndex = mScreenShow - 1;
    }

    public ChartView2(Context context) {
        this(context, null);
    }

    public ChartView2(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ChartView2(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        //  Log.i(TAG, "onMeasure");

        int measuredWidth = measureWidth(widthMeasureSpec);
        int measuredHeight = measureHeight(heightMeasureSpec);
        setMeasuredDimension(measuredWidth, measuredHeight);

        mViewHeight = getMeasuredHeight();
        mViewWidth = getMeasuredWidth();
        mRectFChartViewTouch = new RectF(0, 0, mViewWidth, mViewHeight);
        mLengthX = mViewWidth;
        mLengthY = mViewHeight - mPaddingTop - mPaddingBottom;
        switch (mMode) {
            case HISTOGRAM:
                mUnitX = ((float) mLengthX - mHistogramStrokeWidth) / (float) mSegments;
                break;
            case BROKENLINE:
                mUnitX = ((float) mLengthX - mBrokenLineRadius * 2 - mBrokenLineStrokeWidth) / (float) mSegments;
                break;
        }
        //  Log.i(TAG, "unitx=" + mUnitX);
        rebuild();
    }

    private int measureHeight(int heightMeasureSpec) {
        int measuredHeight = 0;

        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (heightMode == MeasureSpec.EXACTLY) {
            measuredHeight = heightSize;
        } else {
            measuredHeight = mDefaultMinHeight;
            if (heightMode == MeasureSpec.AT_MOST) {
                measuredHeight = Math.min(measuredHeight, heightSize);
            }
        }
        return measuredHeight;
    }

    private int measureWidth(int widthMeasureSpec) {
        int measuredWidth = 0;

        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            measuredWidth = widthSize;
        } else {
            measuredWidth = mDefaultMinWidth;
            if (widthMode == MeasureSpec.AT_MOST) {
                measuredWidth = Math.min(measuredWidth, widthSize);
            }
        }
        return measuredWidth;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        Log.i(TAG, "onDraw");
        drawCoordinate(canvas);
        switch (mMode) {
            case HISTOGRAM:
                drawHistogram(canvas);
                break;
            case BROKENLINE:
                drawBrokenLine(canvas);
                break;
        }
    }


    private void drawBrokenLine(Canvas canvas) {
        if (mData == null) return;
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mBrokenLineColor);
        mPaint.setStrokeWidth(mBrokenLineStrokeWidth);
        mPath.rewind();
        mPath.moveTo(mBrokenLineRadius + mBrokenLineStrokeWidth / 2, mViewHeight - mPaddingBottom - (mData.get(0).y * mUnitY));
        for (int i = 1; i < mData.size(); i++) {
            mPath.lineTo((i * mUnitX) + mBrokenLineRadius + mBrokenLineStrokeWidth / 2, mViewHeight - mPaddingBottom - (mData.get(i).y * mUnitY));
        }
        canvas.drawPath(mPath, mPaint);
        for (int i = 0; i < mData.size(); i++) {
            canvas.drawCircle((i * mUnitX) + mBrokenLineRadius + mBrokenLineStrokeWidth / 2, mViewHeight - mPaddingBottom - (mData.get(i).y * mUnitY), mBrokenLineRadius, mPaint);
        }
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setColor(mBgColor.getColor());
        for (int i = 0; i < mData.size(); i++) {
            canvas.drawCircle((i * mUnitX) + mBrokenLineRadius + mBrokenLineStrokeWidth / 2, mViewHeight - mPaddingBottom - (mData.get(i).y * mUnitY), mBrokenLineRadius - mBrokenLineStrokeWidth / 2, mPaint);
        }
    }


    private void drawHistogram(Canvas canvas) {
        if (mData == null) return;
        mPaint.setColor(mHistogramColor);
        mPaint.setStrokeWidth(mHistogramStrokeWidth);
        for (int i = 0; i < mData.size(); i++) {
            canvas.drawLine((i * mUnitX) + mHistogramStrokeWidth / 2, mViewHeight - mPaddingBottom, (i * mUnitX) + mHistogramStrokeWidth / 2, mViewHeight - mPaddingBottom - (mData.get(i).y * mUnitY), mPaint);
        }
    }

    private void drawCoordinate(Canvas canvas) {
        mPaint.setColor(mCoordinateColor);
        mPaint.setStrokeWidth(mCoordinateStrokeWidth);
        float stopX = mData.size() < mScreenShow ? mViewWidth : mUnitX * mData.size();
        canvas.drawLine(0, mViewHeight - mPaddingBottom + mCoordinateStrokeWidth / 2, stopX, mViewHeight - mPaddingBottom + mCoordinateStrokeWidth / 2, mPaint);//more a unitx
    }

    public void setData(ArrayList<PointF> data) {
        if (data == null) return;
        mData = data;
        rebuild();
        invalidate();
    }

    private void rebuild() {
        calcUnitY();
        switch (mMode) {
            case HISTOGRAM:
                mContentWidth = mData == null ? 0 : (mData.size() - 1) * mUnitX + mHistogramStrokeWidth;
                break;
            case BROKENLINE:
                mContentWidth = mData == null ? 0 : (mData.size() - 1) * mUnitX + 2 * mBrokenLineRadius + mBrokenLineStrokeWidth;
                break;
        }
    }

    /**
     * 得到当前显示屏的value最大值
     */
    private void calcValueMax() {
        if (mData == null) return;
        for (int i = mFrontIndex; i <= mBehindIndex + 1 && mBehindIndex + 1 <= mData.size() - 1; i++) {
            PointF pointF = mData.get(i);
            if (i == mFrontIndex) {
                mValueMax = pointF.y;
                continue;
            }
            mValueMax = pointF.y > mValueMax ? pointF.y : mValueMax;
        }
    }

    /**
     * 根据value最大值得到Y单位量
     */
    private void calcUnitY() {
        calcValueMax();
        mUnitY = (float) mLengthY / mValueMax;
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                Log.i(TAG, "ACTION_DOWN");
                scrollBy(20, 0);
                break;
        }
        return true;
    }


}
